% draws structure of connectome, input and output layer, marks synapses
% according to their weights. It needs as argument only connectome object.
function [hFig] = drawConnectome( connectome )
    %% initialization of figure
    hFig = figure(1);
    clf(hFig);  % clear figure
    width = 1000;
    height = 500;
    maximalSynapseWidth = 5;
    set(hFig, 'Position', [100 0 width height]);
    axis([0 1000 0 500]);
    axis off;
    hold on;
    leftMargin = 5;             % left margin of whole drawing
    leftConnectomeMargin = 100; % left margin of Connectome (before 
                                % connectome there will be a input layer)
    leftOutputMargin = 25;      % space between last layer of connectome and output
                                % layer
    topMargin = 5;
    sizeOfRectangle = 10;       %half of the square line which is symbol for neuron
    VerticalDistanceBetweenNeuronInLayer = ((height - 2*topMargin) / connectome.maximalNumberOfNeuronsInLayer);
    HorizontalDistanceBetweenNeuronInLayer = ((width - 2*leftMargin) / (connectome.numberOfLayers+2));
    
    
    %% Draw synapses
    for i=1:length(connectome.synapses)
        synapse = connectome.synapses(i);
        
        Weight = synapse.weight;                 % synapse weight
        InId = synapse.inputNeuronId;
        InLay = synapse.inputNeuronLayer;
        OutId = synapse.outputNeuronId;
        OutLay = synapse.outputNeuronLayer;
       
        %% find start of synapse
        if(InLay == 0)
            numberOfNeuronsInCurrentLayer = connectome.inputSize;

            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                StartPositionX = (leftConnectomeMargin - leftMargin)/2;
                StartPositionY = (height -(2*topMargin))/2 + (InId-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
            else
                StartPositionX = (leftConnectomeMargin - leftMargin)/2;
                StartPositionY = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (InId -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
            end
        elseif(InLay >= 1 && InLay <= connectome.numberOfLayers)
            numberOfNeuronsInCurrentLayer = connectome.neuronInLayerVector(InLay);
            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                StartPositionX = leftMargin + leftConnectomeMargin + (InLay-1)*HorizontalDistanceBetweenNeuronInLayer;
                StartPositionY = (height -(2*topMargin))/2 + (InId-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
            else
                StartPositionX = leftMargin + leftConnectomeMargin + (InLay-1)*HorizontalDistanceBetweenNeuronInLayer;
                StartPositionY = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (InId -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
            end
        else
            numberOfNeuronsInCurrentLayer = connectome.outputSize;
            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                StartPositionX = leftConnectomeMargin + leftMargin + HorizontalDistanceBetweenNeuronInLayer * connectome.numberOfLayers + leftOutputMargin;
                StartPositionY = (height -(2*topMargin))/2 + (InId-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
            else
                StartPositionX = leftConnectomeMargin + leftMargin + HorizontalDistanceBetweenNeuronInLayer * connectome.numberOfLayers + leftOutputMargin;
                StartPositionY = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (InId -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
            end
        end
        
        %% find end of synapse
        if(OutLay == 0)
            numberOfNeuronsInCurrentLayer = connectome.inputSize;

            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                EndPositionX = (leftConnectomeMargin - leftMargin)/2;
                EndPositionY = (height -(2*topMargin))/2 + (OutId-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
            else
                EndPositionX = (leftConnectomeMargin - leftMargin)/2;
                EndPositionY = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (OutId -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
            end
        elseif(OutLay >= 1 && OutLay <= connectome.numberOfLayers)
            numberOfNeuronsInCurrentLayer = connectome.neuronInLayerVector(OutLay);
            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                EndPositionX = leftMargin + leftConnectomeMargin + (OutLay-1)*HorizontalDistanceBetweenNeuronInLayer;
                EndPositionY = (height -(2*topMargin))/2 + (OutId-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
            else
                EndPositionX = leftMargin + leftConnectomeMargin + (OutLay-1)*HorizontalDistanceBetweenNeuronInLayer;
                EndPositionY = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (OutId -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
            end
        else
            numberOfNeuronsInCurrentLayer = connectome.outputSize;
            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                EndPositionX = leftConnectomeMargin + leftMargin + HorizontalDistanceBetweenNeuronInLayer * connectome.numberOfLayers + leftOutputMargin;
                EndPositionY = (height -(2*topMargin))/2 + (OutId-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
            else
                EndPositionX = leftConnectomeMargin + leftMargin + HorizontalDistanceBetweenNeuronInLayer * connectome.numberOfLayers + leftOutputMargin;
                EndPositionY = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (OutId -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
            end
        end
        minSynapseWeight = 0;
        maxSynapseWeight = 50;
        synapseLineWidth = (Weight - minSynapseWeight+1)/(maxSynapseWeight - minSynapseWeight+1)*maximalSynapseWidth;
        patch([StartPositionX, EndPositionX],...,
                        [StartPositionY, EndPositionY],'k', 'LineWidth', synapseLineWidth);
    end
    
    %% Draw connectome
    for i=1:length(connectome.neurons)
        neuron = connectome.neurons(i);
        
        neuronLayer = neuron.layer;
        numberInLayer = neuron.numberInLayer;
        
        if(neuronLayer == 0)
            numberOfNeuronsInCurrentLayer = connectome.inputSize;

            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                XPosition = (leftConnectomeMargin - leftMargin)/2;
                YPosition = (height -(2*topMargin))/2 + (numberInLayer-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
                patch([XPosition-sizeOfRectangle, XPosition-sizeOfRectangle, XPosition+sizeOfRectangle, XPosition+sizeOfRectangle],...,
                        [YPosition-sizeOfRectangle, YPosition+sizeOfRectangle, YPosition+sizeOfRectangle, YPosition-sizeOfRectangle],'b');
            else
                XPosition = (leftConnectomeMargin - leftMargin)/2;
                YPosition = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (numberInLayer -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
                patch([XPosition-sizeOfRectangle, XPosition-sizeOfRectangle, XPosition+sizeOfRectangle, XPosition+sizeOfRectangle],...,
                        [YPosition-sizeOfRectangle, YPosition+sizeOfRectangle, YPosition+sizeOfRectangle, YPosition-sizeOfRectangle],'b');
            end
        elseif (neuronLayer >= 1 && neuronLayer <= connectome.numberOfLayers)
            numberOfNeuronsInCurrentLayer = connectome.neuronInLayerVector(neuronLayer);

            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                XPosition = leftMargin + leftConnectomeMargin + (neuronLayer-1)*HorizontalDistanceBetweenNeuronInLayer;
                YPosition = (height -(2*topMargin))/2 + (numberInLayer-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
                patch([XPosition-sizeOfRectangle, XPosition-sizeOfRectangle, XPosition+sizeOfRectangle, XPosition+sizeOfRectangle],...,
                        [YPosition-sizeOfRectangle, YPosition+sizeOfRectangle, YPosition+sizeOfRectangle, YPosition-sizeOfRectangle],'g');
            else
                XPosition = leftMargin + leftConnectomeMargin + (neuronLayer-1)*HorizontalDistanceBetweenNeuronInLayer;
                YPosition = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (numberInLayer -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
                patch([XPosition-sizeOfRectangle, XPosition-sizeOfRectangle, XPosition+sizeOfRectangle, XPosition+sizeOfRectangle],...,
                        [YPosition-sizeOfRectangle, YPosition+sizeOfRectangle, YPosition+sizeOfRectangle, YPosition-sizeOfRectangle],'r');
            end
        else

            numberOfNeuronsInCurrentLayer = connectome.outputSize;

            if(mod(numberOfNeuronsInCurrentLayer,2) == 1)
                XPosition = leftConnectomeMargin + leftMargin + HorizontalDistanceBetweenNeuronInLayer * connectome.numberOfLayers + leftOutputMargin;
                YPosition = (height -(2*topMargin))/2 + (numberInLayer-(numberOfNeuronsInCurrentLayer+1)/2)*VerticalDistanceBetweenNeuronInLayer;
                patch([XPosition-sizeOfRectangle, XPosition-sizeOfRectangle, XPosition+sizeOfRectangle, XPosition+sizeOfRectangle],...,
                        [YPosition-sizeOfRectangle, YPosition+sizeOfRectangle, YPosition+sizeOfRectangle, YPosition-sizeOfRectangle],'y');
            else
                XPosition = leftConnectomeMargin + leftMargin + HorizontalDistanceBetweenNeuronInLayer * connectome.numberOfLayers + leftOutputMargin;
                YPosition = (height -(2*topMargin))/2 -0.5*VerticalDistanceBetweenNeuronInLayer + (numberInLayer -(numberOfNeuronsInCurrentLayer)/2)*VerticalDistanceBetweenNeuronInLayer;
                patch([XPosition-sizeOfRectangle, XPosition-sizeOfRectangle, XPosition+sizeOfRectangle, XPosition+sizeOfRectangle],...,
                        [YPosition-sizeOfRectangle, YPosition+sizeOfRectangle, YPosition+sizeOfRectangle, YPosition-sizeOfRectangle],'y');
            end
        end
    end
end

